using AutoMapper;
using MediatR;
using S.O.Domain.Medical;
using S.O.Domain.Dto.Output;
using S.O.ErrorCode;
using S.O.Interstructrue.Base;
using S.O.Api.Read.Application.Command.Medical;

namespace S.O.Api.Read.Application.Handler.Medical
{
    /// <summary>
    /// 获取挂号记录列表处理器
    /// 负责处理挂号记录列表查询的业务逻辑，支持分页和多条件搜索
    /// </summary>
    public class GetRegistrationListHandler : IRequestHandler<GetRegistrationListCommand, APIPaging<GetRegistrationListDto>>
    {
        /// <summary>
        /// 挂号记录仓储接口，用于挂号记录数据的查询操作
        /// </summary>
        private readonly IBaseRepository<RegistrationModel> registrationRepository;
        
        /// <summary>
        /// 日志记录器，用于记录操作日志和错误信息
        /// </summary>
        private readonly ILogger<GetRegistrationListHandler> logger;
        
        /// <summary>
        /// 对象映射器，用于Model对象到DTO对象的转换
        /// </summary>
        private readonly IMapper mapper;
        
        /// <summary>
        /// 构造函数，通过依赖注入初始化所需的服务
        /// </summary>
        /// <param name="registrationRepository">挂号记录仓储服务</param>
        /// <param name="mapper">对象映射服务</param>
        /// <param name="logger">日志记录服务</param>
        public GetRegistrationListHandler(
            IBaseRepository<RegistrationModel> registrationRepository,
            IMapper mapper,
            ILogger<GetRegistrationListHandler> logger)
        {
            this.registrationRepository = registrationRepository;
            this.mapper = mapper;
            this.logger = logger;
        }
        
        /// <summary>
        /// 处理获取挂号记录列表命令
        /// 执行挂号记录列表查询操作，支持按卡号、患者姓名、科室、状态等条件搜索和分页
        /// </summary>
        /// <param name="request">获取挂号记录列表命令对象，包含分页参数和搜索条件</param>
        /// <param name="cancellationToken">取消令牌，用于取消异步操作</param>
        /// <returns>返回包含分页挂号记录列表数据的APIPaging对象</returns>
        public Task<APIPaging<GetRegistrationListDto>> Handle(GetRegistrationListCommand request, CancellationToken cancellationToken)
        {
            // 初始化分页返回结果对象
            APIPaging<GetRegistrationListDto> res = new APIPaging<GetRegistrationListDto>();
            
            try
            {
                // 获取所有未删除的挂号记录数据
                var registrations = registrationRepository.GetALL().Where(x => x.IsDeleted == false);
                
                // 根据卡号进行模糊匹配过滤
                if (!string.IsNullOrWhiteSpace(request.CardNo))
                {
                    registrations = registrations.Where(x => x.CardNo.Contains(request.CardNo));
                }
                
                // 按创建时间降序排列，获取总记录数
                var totalCount = registrations.Count();
                
                // 执行分页处理，根据页码和页大小获取当前页的数据
                var pagedData = registrations
                    .OrderByDescending(x => x.CreateTime)
                    .Skip((request.PageIndex - 1) * request.PageSize)
                    .Take(request.PageSize)
                    .ToList();
                
                // 使用AutoMapper将Model对象转换为DTO对象
                var dtoList = mapper.Map<List<GetRegistrationListDto>>(pagedData);
                
                // 设置返回结果
                res.Code = APIEnums.Success;
                res.PageDatas = dtoList;
                res.TotalCount = totalCount;
                res.Msg = "获取挂号记录列表成功";
                
                // 记录操作日志
                logger.LogInformation($"获取挂号记录列表成功，共{totalCount}条记录，当前页{request.PageIndex}，页大小{request.PageSize}");
            }
            catch (Exception ex)
            {
                // 异常处理
                res.Code = APIEnums.Error;
                res.Msg = "获取挂号记录列表失败";
                logger.LogError(ex, "获取挂号记录列表时发生异常");
            }
            
            return Task.FromResult(res);
        }
    }
}